﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bruce.Net;
using Game.Foundation;
using Game.Foundation.Client;

namespace Game.Client
{
    public class GameConnection
    {
        private static List<GameConnection> m_connectionList = new List<GameConnection>();

        public static GameConnection CreateConnection(AsyncWorkSocket socket, string gamename, int areaId, int roomId)
        {
            GameConnection connection = m_connectionList.SingleOrDefault(c => c.GameName == gamename && c.AreaID == areaId && c.RoomID == roomId);
            if (connection == null)
            {
                connection = new GameConnection(socket, gamename, areaId, roomId);
                m_connectionList.Add(connection);
            }

            return connection;
        }

        public static GameConnection GetConnection(string key)
        {
            return m_connectionList.SingleOrDefault(c => c.Key == key);
        }

        private AsyncWorkSocket _connection;
        public string GameName { get; private set; }
        public int AreaID { get; private set; }
        public int RoomID { get; private set; }
        public string Key
        {
            get
            {
                return string.Format("{0}|{1}|{2}", this.GameName, this.AreaID, this.RoomID);
            }
        }

        public event EventHandler<GameListEventArgs> ReceivedGameList;
        public event EventHandler<BasicEventArgs> ReceivedLoginResponse;
        public event EventHandler<ChatEventArgs> ReceivedChatInfo;
        public event EventHandler<GameGroupCollectionEventArgs> ReceivedGameGroupList;
        public event EventHandler<GameGroupChangedEventArgs> GameGroupChanged;
        public event EventHandler<PacketEventArgs> ReceicedNewGameNotify;
        public event EventHandler<ExchangeHandEventArgs> CurrentHandExchanged;
        public event EventHandler<PacketEventArgs> ChessmanLocationMoved;
        public event EventHandler<PacketEventArgs> GameCompleted;

        private GameConnection(AsyncWorkSocket connection, string username, int areaId, int roomId)
        {
            this._connection = connection;
            this._connection.PacketReceived += new EventHandler<PacketEventArgs>(_connection_PacketReceived);
            this.GameName = username;
            this.AreaID = areaId;
            this.RoomID = roomId;

            Packet p = new Packet((int)PacketType.进入房间请求);
            p.WriteInt32(areaId);
            p.WriteInt32(roomId);
            p.WriteString(username);
            this._connection.Send(p);
        }

        public void SendChatMessage(string content)
        {
            Packet p = new Packet((int)PacketType.发送聊天信息请求);
            p.WriteString(content);

            this._connection.Send(p);
        }

        public void JoinGameGroup(int areaId, int roomId, int deskId, byte index)
        {
            Packet p = new Packet((int)PacketType.加入游戏分组请求);
            p.WriteInt32(areaId);
            p.WriteInt32(roomId);
            p.WriteInt32(deskId);
            p.WriteByte(index);

            this._connection.Send(p);
        }

        public void MoveChessman(int xOld,int yOld,int xNew,int yNew)
        {
            Packet p = new Packet((int)PacketType.游戏操作请求包);
            p.WriteInt32(xOld);
            p.WriteInt32(yOld);
            p.WriteInt32(xNew);
            p.WriteInt32(yNew);

            this._connection.Send(p);
        }

        public void MoveChessman(Packet p)
        {
            if (p != null && p.Protocol == (int)PacketType.游戏操作请求包)
            {
                this._connection.Send(p);
            }
        }

        void _connection_PacketReceived(object sender, PacketEventArgs e)
        {
            Packet p = e.Packet as Packet;
            //this.DoActionCrossThreads(() => txtMessageHistory.Text += p.Type.ToString() + Environment.NewLine);
            PacketType type = (PacketType)p.Protocol;
            switch (type)
            {
                case PacketType.游戏列表返回包:
                    //ProcessGameList(p);
                    break;

                case PacketType.进入房间返回:
                    ProcessLoginResponse(p);
                    break;

                case PacketType.发送聊天信息返回:
                    break;

                case PacketType.聊天信息到达通知:
                    ProcessChatInfo(p);
                    break;
                case PacketType.分组列表返回包:
                    ProcessGameGroupListResponse(p);
                    break;

                case PacketType.分组列表改变通知包:
                    ProcessGameGroupChanged(p);
                    break;

                case PacketType.游戏开始通知:
                    ProcessNewGame(p);
                    break;

                case PacketType.游戏换手操作通知包:
                    ProcessExchangeHand(p);
                    break;

                case PacketType.游戏操作同步包:
                    ProcessChessMove(p);
                    break;

                case PacketType.游戏结束通知:
                    ProcessGameResult(p);
                    break;
            }
        }

        private void ProcessGameList(Packet p)
        {
            if (this.ReceivedGameList == null) return;

            GameListEventArgs e = new GameListEventArgs();
            GameConfig game = new GameConfig();
            game.Name = p.ReadString();
            game.IPAddress = p.ReadString();
            game.Port = p.ReadInt32();
            game.SeatCount = p.ReadInt32();
            int areaCount = p.ReadInt32();
            for (int i = 0; i < areaCount; i++)
            {
                GameAreaConfig area = new GameAreaConfig();
                area.ID = p.ReadInt32();
                area.Name = p.ReadString();
                int roomCount = p.ReadInt32();

                for (int j = 0; j < roomCount; j++)
                {
                    GameRoomConfig room = new GameRoomConfig();
                    room.ID = p.ReadInt32();
                    room.Name = p.ReadString();
                    //int deskCount = translater.GetInt();

                    area.RoomList.Add(room);
                }

                game.AreaList.Add(area);
            }
            e.GameList.Add(game);

            this.ReceivedGameList(this, e);
        }

        private void ProcessLoginResponse(Packet p)
        {
            if (this.ReceivedLoginResponse == null) return;

            BasicEventArgs e = new BasicEventArgs();
            e.ReturnCode = p.OptionOne;
            this.ReceivedLoginResponse(this, e);
        }

        private void ProcessChatInfo(Packet p)
        {
            if (this.ReceivedChatInfo == null) return;

            ChatEventArgs e = new ChatEventArgs();
            e.Content = p.ReadString();

            this.ReceivedChatInfo(this, e);
        }

        private void ProcessGameGroupListResponse(Packet p)
        {
            if (this.ReceivedGameGroupList == null) return;

            GameGroupCollectionEventArgs e = new GameGroupCollectionEventArgs();
            int groupCount = p.ReadInt32();

            for (int i = 0; i < groupCount; i++)
            {
                GameGroup group = new GameGroup();
                group.ID = p.ReadInt32();
                int roleCount = p.ReadInt32();
                for (int j = 0; j < roleCount; j++)
                {
                    group.RoleList.Add(new Role
                    {
                        UserName = p.ReadString(),
                        SeatIndex = p.ReadByte(),
                        Status = (GameStatus)p.ReadByte(),
                    });
                }

                e.GroupList.Add(group);
            }

            this.ReceivedGameGroupList(this, e);

        }

        private void ProcessGameGroupChanged(Packet p)
        {
            if (this.GameGroupChanged == null) return;

            GameGroupChangedEventArgs e = new GameGroupChangedEventArgs();
            e.ChangeType = (GameStatus)p.OptionOne;
            e.GroupID = p.ReadInt32();
            e.SeatIndex = p.ReadByte();
            e.UserName = p.ReadString();

            this.GameGroupChanged(this, e);
        }

        private void ProcessNewGame(Packet p)
        {
            if (this.ReceicedNewGameNotify == null) return;

            PacketEventArgs e = new PacketEventArgs(p);
            this.ReceicedNewGameNotify(this, e);
        }

        private void ProcessExchangeHand(Packet p)
        {
            if (this.CurrentHandExchanged == null) return;

            ExchangeHandEventArgs e = new ExchangeHandEventArgs();
            e.CurrentSeat = p.ReadByte();
            e.CurrentUserName = p.ReadString();

            this.CurrentHandExchanged(this, e);
        }

        private void ProcessChessMove(Packet p)
        {
            if (this.ChessmanLocationMoved == null) return;

            PacketEventArgs e = new PacketEventArgs(p);

            this.ChessmanLocationMoved(this, e);
        }

        private void ProcessGameResult(Packet p)
        {
            if (this.GameCompleted == null) return;
            PacketEventArgs e = new PacketEventArgs(p);

            this.GameCompleted(this, e);
        }

        public void ChangeReadyStatus(GameStatus target)
        {
            Packet p = new Packet((int)PacketType.准备游戏操作请求);
            p.OptionOne = (byte)target;

            this._connection.Send(p);
        }
    }
}
